package com.ljcalc.business.components;

import java.io.*;
import java.net.*;
import java.util.*;

import com.ljcalc.business.components.fetchers.HTTPFetcher;
import com.ljcalc.business.components.requests.IntegerUserRequest;

public class RandomPoolManager {
	
	private static RandomPoolManager instance;
	private final static int DEFAULT_SIZE = 100;
	private HashMap<String,RandomPool> poolsMap = null;
	private HTTPFetcher httpFetcher = null;
	
	private RandomPoolManager(){
		poolsMap = new HashMap<String, RandomPool>();
		httpFetcher = new HTTPFetcher("");
	}
	
	public static RandomPoolManager getInstance(){
		if(instance==null){
			instance = new RandomPoolManager();
		}
		return instance;
	}

	private RandomPool generateRandomPool(int size, int min, int max){
		IntegerUserRequest ur = new IntegerUserRequest(size,min,max);
		httpFetcher.setUserRequest(ur);
		RandomPool pool = null;
		try {
			httpFetcher.loadContent();
			pool = new RandomPool(httpFetcher.getContent());
		} catch (MalformedURLException e) {
			e.printStackTrace();
			pool = null;
		} catch (IOException ex){
			ex.printStackTrace();
			pool = null;
		}
		return pool;
	}
	
	public RandomPool getRandomPool(int min, int max){
		return getRandomPool(min,max, Collections.EMPTY_LIST);
	}
	
	/**
	 * get the random pool contains value from min to max but exclude the values in the list
	 * @param min
	 * @param max
	 * @param list, contains the values to be excluded
	 * @return
	 */
	public RandomPool getRandomPool(int min, int max, List<Long> list){
		RandomPool ret = poolsMap.get(getKey(min,max,list));
		if(ret==null||ret.size()==0){
			ret = generateRandomPool(DEFAULT_SIZE, min, max);
			Iterator<Long> itr = list.iterator();
			while (itr.hasNext()) {
				Long object = (Long) itr.next();
				while(ret.remove(object));
			}

			poolsMap.put((String)getKey(min,max,list), ret);
		}
		return ret;
	}

	/**
	 * create key for the list values excluding pool
	 * @param min
	 * @param max
	 * @param list
	 * @return
	 */
	private Object getKey(int min, int max, List<Long> list) {
		String key = getKey(min,max);		
		Iterator<Long> itr = list.iterator();
		while (itr.hasNext()) {
			Long object = (Long) itr.next();
			key = key + "-" + object;
		}
		return key;
	}

	public RandomPool getRandomPool(int min, int max, boolean forceToGenerate){
		RandomPool ret = poolsMap.get(getKey(min,max));
		if((ret==null||ret.size()==0)&&forceToGenerate){
			ret = generateRandomPool(DEFAULT_SIZE, min, max);
			poolsMap.put(getKey(min,max), ret);
		}
		return ret;
	}
	
	
	private String getKey(int min, int max){
		return min+":"+max;
	}
}
